package org.jeecg.config.aspct;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.annotation.Aspect;
import org.jeecg.common.aspect.annotation.ApiLogin;
import org.jeecg.common.exception.ChechDataAuthException;
import org.jeecg.common.exception.JeecgBoot401Exception;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.app.v1.util.Const;
import org.jeecg.modules.power.group.entity.GroupUser;
import org.jeecg.modules.power.group.service.IYlGroupService;
import org.jeecg.modules.power.user.entity.YlToken;
import org.jeecg.modules.power.user.entity.YlUser;
import org.jeecg.modules.power.user.mapper.YlTokenMapper;
import org.jeecg.modules.power.user.mapper.YlUserMapper;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 校验数据查询权限的问题 集成了ApiLogin，但只校验app运营账号，不校验小程序用户信息
 * @author scw
 * @version v1.0
 * @date 2024-07-24
 */
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class ApiCheckDataAuthAspct implements HandlerInterceptor {

    public static final String SYS_USER = "sysUser";//用户对象

    private final YlTokenMapper ylTokenMapper;//token表
    private final SysUserMapper userMapper;//运营端
    private final IYlGroupService ylGroupService; //小组

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) {
        ApiCheckDataAuth apiCheckDataAuth;
        if(object instanceof HandlerMethod) {
            apiCheckDataAuth = ((HandlerMethod) object).getMethodAnnotation(ApiCheckDataAuth.class);
        }else{
            return true;
        }
        if(apiCheckDataAuth == null){
            return true;
        }
        String errMsg="登陆已超时！请重新登陆";
        String token = request.getHeader("token"); // 从 http 请求头中取出 token
        if(StringUtils.isBlank(token)){
            throw new JeecgBoot401Exception("请登录!");
        }
        //设置userId到request里，后续根据userId，获取用户信息
        YlToken ylToken=ylTokenMapper.getToken(token);
        if (oConvertUtils.isEmpty(ylToken)){
            throw new JeecgBoot401Exception("你的账号在其他设备登陆!");//自定义异常处理
        }
        //判定 有没有超时
        if( ylToken.getExpireTime().getTime()<System.currentTimeMillis()){
            ylTokenMapper.delGasToken(token);//清除过期token
            throw new JeecgBoot401Exception(errMsg);//自定义异常处理
        }
        if (ylToken.getType()!=1)throw new ChechDataAuthException("无数据查询权限");//自定义异常处理
            //运营
        SysUser user = userMapper.selectById(ylToken.getUserId());
        if (oConvertUtils.isEmpty(user)){
            throw new JeecgBoot401Exception(errMsg);//自定义异常处理
        }
        if (user.getStatus()==2){// 状态(1：正常  2：冻结 ）
            throw new JeecgBoot401Exception("账号已被冻结！请联系管理员");//自定义异常处理
        }
        request.setAttribute(SYS_USER, user);

        /**
         * 校验数据权限
         */
        GroupUser groupUser = ylGroupService.getUserGroup(user.getId());
        /**
         * 获取到所查数据的权限（对应的小组ID或者组员ID）
         * flag 标记当前所查数据权限为小组或者组员  1小组（groupId为所在小组ID）2组员（groupId为组员ID）
         */
//        Object flag = request.getAttribute("flag");
//        Object groupId = request.getAttribute("groupId");
        Object flag = request.getParameter("flag")==null?request.getAttribute("flag"): request.getParameter("flag");
        Object groupId = request.getParameter("groupId")==null?request.getAttribute("flag"): request.getParameter("groupId");

        if(oConvertUtils.isEmpty(flag))throw new ChechDataAuthException("查询数据标志错误，flag=null");
        if(oConvertUtils.isEmpty(groupId))throw new ChechDataAuthException("查询数据权限错误，groupId=null");
        /**
         * 判断逻辑：
         *   如果所查权限与当前登录用户的ID一致，不予校验直接通过
         *   反之，则判断当前登录用户是否为组长，如果不是组长则无权限，
         *   如果是组长，则查询是否为他所在的小组或者小组成员，若不是则无权限
         */
        if(Objects.equals(flag.toString(), Const.leader_1)) {
            /**
             * 查询小组数据时groupId为所查询小组的ID
             */
            if (!Objects.equals(groupUser.getIsLeader(), Const.leader_1)) {
                /**不是组长无权限查看*/
                throw new ChechDataAuthException("无组长查询权限");
            }else {
                /**不是组长，非本组数据不能查看*/
                if(!Objects.equals(groupUser.getGroupId(), groupId.toString())) throw new ChechDataAuthException("无查询权限");
            }
        }else{
            /**
             * 查询BD数据时groupId为所查询BD的ID
             */
            if (!Objects.equals(groupUser.getIsLeader(), Const.leader_1)) {
                /**不是组长，非本人数据不能查看*/
                if(!Objects.equals(groupUser.getUserId(), groupId.toString())) throw new ChechDataAuthException("无查询权限");
//                throw new ChechDataAuthException("无组长查询权限");
            }else {
                GroupUser groupMember = ylGroupService.getUserGroup(groupId.toString());
                /**是组长，但非本组成员不能查看*/
                if(!Objects.equals(groupUser.getGroupId(), groupMember.getGroupId())) throw new ChechDataAuthException("无查询权限");
            }
        }
        return true;
    }
}
